package utils.fileConvert;

import com.alibaba.fastjson.*;
import com.google.common.collect.ImmutableMap;
import com.lkx.util.ExcelParam;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.entity.ContentType;
import org.springframework.mock.web.MockMultipartFile;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.FileInputStream;
import java.util.*;

/**
 * @author Chen Yuan
 * @create 2021-12-22  14:30
 */
@Slf4j
public class ExcelUtil {

	/**
	 * 读取 Excel 文件, 并将结果转成对应的对象,
	 * 使用该方法, 需要在实体类字段上加上注释, 标明和Excel表头的对应关系, 例:
	 *
	 * @param file  Excel 文件
	 * @param clazz 需要转到的类型对象
	 * @param <T>   类型
	 */
	public static <T> List<T> readExcByFile(MultipartFile file, Class<T> clazz) {
		List<T> result = null;
		try {
			ExcelParam excelParam = new ExcelParam();
			excelParam.setClazz(clazz);
			excelParam.setStream(true);
			excelParam.setBuf(file.getBytes());
			result = ExcelUtilBase.commonReadExcel(excelParam);
		} catch (Exception e) {
			log.error("×××× readExcByFile ×× {} ××××××××××\n  ", e.getMessage(), e);
		}
		return result;
	}


	/**
	 * 读取 Excel 文件, 并将结果转成对应的对象,
	 * 使用该方法, 需要在实体类字段上加上注释, 标明和Excel表头的对应关系, 例:
	 *
	 * @param file          Excel 文件
	 * @param clazz         需要转到的类型对象
	 * @param titleRowIndex 标题行所在行号
	 * @param <T>           类型
	 * @return
	 * @Excel(title = "id")
	 * private String id;
	 * @Excel(title = "密码")
	 * private String password;
	 */
	public static <T> List<T> readExcByFile(MultipartFile file, Class<T> clazz, int titleRowIndex) {
		List<T> result = null;
		try {
			ExcelParam excelParam = new ExcelParam();
			excelParam.setClazz(clazz);
			excelParam.setStream(true);
			excelParam.setBuf(file.getBytes());
			excelParam.setRowNumIndex(titleRowIndex);
			result = ExcelUtilBase.commonReadExcel(excelParam);
		} catch (Exception e) {
			log.error("×××× readExcByFile ×× {} ××××××××××\n  ", e.getMessage(), e);
		}
		return result;
	}

	/**
	 * 读取 Excel 文件, 并将结果转成对应的对象
	 *
	 * @param file      Excel 文件
	 * @param columnMap Excel 文件表头名称与实体类对象字段映射关系 - "表头名称:实体类字段名称", 示例 "id:id,password:password", 表头为中文时 "主键:id,密码:password"
	 * @param clazz     需要转到的类型对象
	 * @param <T>       类型
	 */
	public static <T> List<T> readExcByFile(MultipartFile file, String columnMap, Class<T> clazz) {
		List<T> result = null;
		try {
			// 去除字符串中的空格
			columnMap = columnMap.replace(" ", "");
			Map<String, String> map = DBFUtilBase.getMap(columnMap);
			ExcelParam excelParam = new ExcelParam();
			excelParam.setMap(map);
			excelParam.setStream(true);
			excelParam.setClazz(clazz);
			excelParam.setBuf(file.getBytes());
			result = ExcelUtilBase.commonReadExcel(excelParam);
		} catch (Exception e) {
			log.error("×××× readExcByFile ×× {} ××××××××××\n  ", e.getMessage(), e);
		}
		return result;
	}

	/**
	 * 读取 Excel 文件, 并将结果转成对应的对象
	 *
	 * @param file          Excel 文件
	 * @param columnMap     Excel 文件表头名称与实体类对象字段映射关系 - "表头名称:实体类字段名称", 示例 "id:id,password:password", 表头为中文时 "主键:id,密码:password"
	 * @param clazz         需要转到的类型对象
	 * @param titleRowIndex 标题行所在行号
	 * @param <T>           类型
	 */
	public static <T> List<T> readExcByFile(MultipartFile file, String columnMap, Class<T> clazz, int titleRowIndex) {
		List<T> result = null;
		try {
			// 去除字符串中的空格
			columnMap = columnMap.replace(" ", "");
			Map<String, String> map = DBFUtilBase.getMap(columnMap);
			ExcelParam excelParam = new ExcelParam();
			excelParam.setMap(map);
			excelParam.setStream(true);
			excelParam.setClazz(clazz);
			excelParam.setBuf(file.getBytes());
			excelParam.setRowNumIndex(titleRowIndex);
			result = ExcelUtilBase.commonReadExcel(excelParam);
		} catch (Exception e) {
			log.error("×××× readExcByFile ×× {} ××××××××××\n  ", e.getMessage(), e);
		}
		return result;
	}


	/**
	 * 导出Excel到指定磁盘位置
	 */
	public static void exportExcel(String outFilePath, Map<String, String> keyValue, List<?> list, Class clazz, String fileName) throws Exception {
		ExcelParam excelParam = new ExcelParam(clazz, "", outFilePath, list);
		excelParam.setMap(keyValue);
		excelParam.setFileName(fileName);
		excelParam.setHeaderName(fileName);
		ExcelUtilBase.commonExportExcel(excelParam, null);
	}

	public static void exportExcel(String outFilePath, List<?> list, Class clazz) throws Exception {
		ExcelParam excelParam = new ExcelParam(clazz, outFilePath, list);

		if (Objects.equals(clazz, JSONObject.class) &&
				list != null && !list.isEmpty()) {
			JSONObject firstRow = (JSONObject) list.get(0);
			Set<String> keySet = firstRow.keySet();
			Map<String, String> map = new HashMap<>(20);
			for (String key : keySet) {
				map.put(key, key);
			}
			excelParam.setMap(map);
		}

		ExcelUtilBase.commonExportExcel(excelParam, null);
	}

	public static void exportReportExcel(String outFilePath, Map<String, String> keyValue, List<?> list, Class clazz,
	                                     String fileName, Map<String, String> headInfoMap) throws Exception {
		ExcelParam excelParam = new ExcelParam(clazz, "", outFilePath, list);
		excelParam.setMap(keyValue);
		excelParam.setFileName(fileName);
		excelParam.setHeaderName(fileName);
		ExcelUtilBase.commonExportExcel(excelParam, headInfoMap);
	}

	/**
	 * 导出 Excel
	 *
	 * @param keyValue 字段名称, 表头 对照关系, key:字段名, value:表头
	 * @param list     数据列表
	 * @param clazz    数据对象类型
	 * @param fileName 导出文件名
	 */
	public static void exportExcelOutputStream(HttpServletResponse response, Map<String, String> keyValue, List<?> list,
	                                           Class<?> clazz, String fileName) throws Exception {
		ExcelParam excelParam = new ExcelParam(clazz, response, fileName, list);
		excelParam.setMap(keyValue);
		excelParam.setHeaderName(fileName);
		ExcelUtilBase.commonExportExcel(excelParam, null);
	}

	public static void exportExcelOutputStream(HttpServletResponse response, List<?> list, Class<?> clazz) throws Exception {
		ExcelParam excelParam = new ExcelParam(clazz, response, list);
		ExcelUtilBase.commonExportExcel(excelParam, null);
	}

	public static void main(String[] args) throws Exception {
		List list = null;
		String pathOfXls1 = "C:/Users/zovan/Desktop/test1.xlsx";
		String pathOfXls2 = "C:/Users/zovan/Desktop/test2.xlsx";
		String readMap = "id:id,password:password,username:username,user_style:userStyle,source:source,updateDt:updateDt";

		File file = null;
		FileInputStream inputStream = null;
		MultipartFile multipartFile = null;

		// 1. 通过路径读取 Excel
		//list = ExcelUtil.readXlsByPath(pathOfXls, readMap, ExcConvertToDbfCTO.class);

		// 2. 通过文件流读取 Excel
		file = new File(pathOfXls1);
		inputStream = new FileInputStream(file);
		multipartFile = new MockMultipartFile(file.getName(), file.getName(), ContentType.APPLICATION_OCTET_STREAM.toString(), inputStream);
		//list = ExcelUtil.readExcByFile(multipartFile, JSONObject.class, 2);

		ExcelParam excelParam = new ExcelParam();
		excelParam.setClazz(JSONObject.class);
		excelParam.setStream(true);
		excelParam.setBuf(multipartFile.getBytes());
		list = ExcelUtilBase.commonReadExcel(excelParam);

		ExcelUtil.exportReportExcel(pathOfXls2, excelParam.getMap(), list, JSONObject.class, file.getName(), ImmutableMap.of("医疗单位", "常州市德安医院", "制表人", "呵呵", "统计时间", "2021-11-01 00:00:00至2021-12-01-30 23:59:59", "制表时间", JSON.toJSONStringWithDateFormat(new Date(), "yyyy-MM-dd HH:mm:ss")));

		log.info(JSON.toJSONString(list));
	}
}
